using System;
using System.Drawing;
using System.Collections.Generic;
using System.Text;
using System.Threading;

using System.Windows.Forms;
using Weazel.Microblaze.Simulator.Engine;
using Weazel.Microblaze.Simulator.Components.Opb;

namespace Weazel.Microblaze.Simulator.Components.Lcd
{
    public class Lcd : OpbSlaveBase
    {
        private Bitmap bitmap;
        private int x, y;
        private int width, height;

        public Lcd(Simulator.Engine.SimulationContext simulator, uint low, uint high)
            : base(simulator)
        {
            this.HighAddress = high;
            this.LowAddress = low;

            x = 0;
            y = 0;
            width = 512;
            height = 512;
        }

        public override string GetStatusString()
        {
            return "n/a";
        }

        public override void Load(byte[] bytes, uint address)
        {
            throw new NotSupportedException();
        }

        public override void Run()
        {
            while(true)
                WaitClock();
        }


        public override void BeginTransaction(Transaction transaction)
        {
            uint localAddress = transaction.Address - this.LowAddress;

            if (transaction.Type == Transaction.TransactionType.Read)
            {
                switch (localAddress)
                {
                    case 0:
                        {
                            transaction.Value = (uint)width;
                            break;
                        }
                    case 4:
                        {
                            transaction.Value = (uint)height;
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
            }
            else if (transaction.Type == Transaction.TransactionType.Write)
            {
                switch (localAddress)
                {
                    case 0:
                        {
                            this.width = (int)transaction.Value;

                            if (bitmap != null)
                                bitmap.Dispose();

                            bitmap = new Bitmap(width, height);
                            break;
                        }
                    case 4:
                        {
                            this.height = (int)transaction.Value;

                            if (bitmap != null)
                                bitmap.Dispose();

                            bitmap = new Bitmap(width, height);
                            break;
                        }
                    case 8:
                        {
                            ShowBitmap();
                            break;
                        }
                    case 12:
                        {
                            bitmap.SetPixel(x, y, Color.FromArgb((int)transaction.Value, (int)transaction.Value, (int)transaction.Value));

                            // increment the count
                            if (x + 1 < width)
                            {
                                x++;
                            }
                            else if (y + 1 < height)
                            {
                                x = 0;
                                y++;
                            }
                            else
                            {
                                x = 0;
                                y = 0;
                            }

                            break;
                        }

                    default:
                        {
                            break;
                        }
                }
            }

            transaction.Status = Transaction.TransactionStatus.Complete;
        }

      

        private void ShowBitmap()
        {
            Thread t = new Thread(new ThreadStart(showBitmapWindowThreadBody));
            t.Start();
        }

        private void showBitmapWindowThreadBody()
        {
            LcdWindow window = new LcdWindow(new Bitmap(bitmap));
            window.ShowDialog();
            Thread.CurrentThread.Abort();
        }
    }
}
